{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# পার্ট 2: সিফ্ট কেরাসের সাথে সুরক্ষিত মডেল পরিবেশন করা (Secure Model Serving with Syft Keras)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "এখন আপনার কাছে সাধারণ কেরাস সহ একটি প্রশিক্ষিত মডেল রয়েছে, আপনি কিছু ব্যক্তিগত ভবিষ্যদ্বাণী পরিবেশন করতে প্রস্তুত। আমরা সিফ্ট কেরাস ব্যবহার করে এটি করতে পারি।\n",
    "\n",
    "এই মডেলটিকে সুরক্ষিত ও পরিবেশন করতে আমাদের তিনটি টিএফইউইউবার্স (সার্ভার)(TFEWorkers (servers)) লাগবে। এর কারণ হুডের নীচে টিএফ এনক্রিপ্ট(TF Encrypted) করা একটি এনক্রিপশন কৌশল বলে [multi-party computation (MPC)](https://en.wikipedia.org/wiki/Secure_multi-party_computation). ধারণাটি হল মডেল ওজন এবং ইনপুট ডেটাগুলিকে ভাগ করে নেওয়া, তারপরে প্রতিটি মানের একটি অংশ বিভিন্ন সার্ভারে প্রেরণ করুন। মূল বৈশিষ্ট্যটি হ'ল যদি আপনি একটি সার্ভারের ভাগের দিকে তাকান তবে এটি মূল মান (ইনপুট ডেটা বা মডেল ওজন) সম্পর্কে কিছুই প্রকাশ করে না।\n",
    "\n",
    "আমরা পূর্বের নোটবুকের মতো একটি সিফ্ট কেরাস মডেল সংজ্ঞায়িত করব। তবে, একটি কৌশল আছে: এই মডেলটি ইনস্ট্যান্ট করার আগে, আমরা চালাব `hook = sy.KerasHook(tf.keras)`. এটি কেরাস সিক্যুয়ালিয়াল শ্রেণিতে তিনটি গুরুত্বপূর্ণ নতুন পদ্ধতি যুক্ত করবে:\n",
    " - `share`: গোপন ভাগ করে নেওয়ার মাধ্যমে আপনার মডেলটিকে সুরক্ষিত করবে; ডিফল্টরূপে, এটি টিএফ এনক্রিপ্ট করা থেকে সিকিওরএনএন প্রোটোকলটি গোপনে আপনার টিউনকে তিনটি টিএফইউইওয়ারকারের মধ্যে ভাগ করে নেবে secret সর্বাধিক গুরুত্বপূর্ণ, এটি এনক্রিপ্ট করা ডেটাতে পূর্বাভাস সরবরাহের সক্ষমতা যুক্ত করবে।\n",
    " - `serve`: এই ফাংশনটি একটি পরিবেশনকারী সারি চালু করবে, যাতে টিএফইউইউওকাররা বাহ্যিক ক্লায়েন্টদের সুরক্ষিত মডেলটিতে পূর্বাভাসের অনুরোধগুলি গ্রহণ করতে পারে।\n",
    " - `shutdown_workers`: একবার আপনি ব্যক্তিগত পূর্বাভাস সরবরাহ করা হয়ে গেলে, আপনি এই ফাংশনটি চালিয়ে আপনার মডেলটি বন্ধ করতে পারেন। আপনি যদি প্রতিটি কর্মীকে ম্যানুয়ালি পরিচালনা করতে পছন্দ করে থাকেন তবে এটি ম্যানুয়ালি সার্ভার প্রক্রিয়াগুলি বন্ধ করার নির্দেশ দেয়।\n",
    "\n",
    "আপনি যদি আরও জানতে চান MPC সম্মন্ধে,আপনি এই দারুন লেখা টি পড়তে পারেন [blog](https://mortendahl.github.io/2017/04/17/private-deep-learning-with-mpc/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "অনুবাদক:\n",
    "\n",
    "- Sourav Das - Twitter: [@adventuroussrv](https://twitter.com/adventuroussrv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras import Sequential\n",
    "from tensorflow.keras.layers import AveragePooling2D, Conv2D, Dense, Activation, Flatten, ReLU, Activation\n",
    "\n",
    "import syft as sy\n",
    "hook = sy.KerasHook(tf.keras)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## মডেল (Model)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "আপনি দেখতে পাচ্ছেন, আমরা সরবরাহ না করে আমরা আগের মতো প্রায় একই মডেলটি সংজ্ঞায়িত করি​ `batch_input_shape`. এটি অনুমতি দেয় টিএফ এনক্রিপ্ট (TF Encrypted) করা পূর্বনির্ধারিত টেনসর আকারগুলির মাধ্যমে সুরক্ষিত গণনাগুলি আরও ভাল করতে। এই এমএনআইএসটি(MNIST) ডেমোটির জন্য, আমরা আকারের ইনপুট ডেটা প্রেরণ করব (1, 28, 28, 1)।\n",
    "আমরা সফটম্যাক্সের(softmax)পরিবর্তে logit টি ফিরিয়ে দেব কারণ এই অপারেশনটি এমপিসি(MPC) ব্যবহার করে করা জটিল এবং ভবিষ্যদ্বাণীগুলির অনুরোধগুলি সরবরাহ করার জন্য আমাদের এটির দরকার নেই।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_classes = 10\n",
    "input_shape = (1, 28, 28, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = Sequential()\n",
    "\n",
    "model.add(Conv2D(10, (3, 3), batch_input_shape=input_shape))\n",
    "model.add(AveragePooling2D((2, 2)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Conv2D(32, (3, 3)))\n",
    "model.add(AveragePooling2D((2, 2)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Conv2D(64, (3, 3)))\n",
    "model.add(AveragePooling2D((2, 2)))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Flatten())\n",
    "model.add(Dense(num_classes, name=\"logit\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### প্রাক প্রশিক্ষিত weights লোড করুন (Load pre-trained weights)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "সঙ্গে `load_weights` আপনি আপনার মডেলটি প্রশিক্ষণের পরে আপনি যে ওজনগুলি সংরক্ষণ করেছেন সেগুলি সহজেই লোড করতে পারেন।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pre_trained_weights = 'short-conv-mnist.h5'\n",
    "model.load_weights(pre_trained_weights)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### চালু করুন workers (Launch the workers)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "আসুন এখন তৈরি করা যাক TFEWorkers (`alice`, `bob`, and `carol`) ব্যক্তিগত ভবিষ্যদ্বাণী সম্পাদনের জন্য টিএফ এনক্রিপ্ট(TF Encrypted) দ্বারা প্রয়োজনীয়। প্রতিটি TFEWorker জন্য আপনাকে কেবল একটি হোস্ট নির্দিষ্ট করতে হবে। এরপরে আমরা একটি cluster এই workers একত্রিত করি।\n",
    "\n",
    "এই workers [TensorFlow server](https://www.tensorflow.org/api_docs/python/tf/distribute/Server), যা আপনি হয় করচালিত পরিচালনা করতে পারেন (`AUTO = False`) তাঁর জিজ্ঞাসা টি workers আপনার জন্য পরিচালনা করতে (`AUTO = True`). যদি সেগুলি ম্যানুয়ালি পরিচালনা করতে চান, কল করার পরে আপনাকে প্রতিটি কর্মীর হোস্ট ডিভাইসে একটি টার্মিনাল কমান্ড কার্যকর করতে নির্দেশ দেওয়া হবে `cluster.start()` নিচে. যদি সমস্ত কর্মী একটি ডিভাইসে হোস্ট করা হয় (e.g. `localhost`), আপনি সিফ্টটি স্বয়ংক্রিয়ভাবে worker's টেনসরফ্লো(TensorFlow) সার্ভারটি পরিচালনা করতে পারবেন।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "AUTO = False\n",
    "\n",
    "alice = sy.TFEWorker(host='localhost:4000', auto_managed=AUTO)\n",
    "bob = sy.TFEWorker(host='localhost:4001', auto_managed=AUTO)\n",
    "carol = sy.TFEWorker(host='localhost:4002', auto_managed=AUTO)\n",
    "\n",
    "cluster = sy.TFECluster(alice, bob, carol)\n",
    "cluster.start()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Weights ভাগ করে মডেলটি সুরক্ষিত করুন  (Secure the model by sharing the weights)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ধন্যবাদ `sy.KerasHook(tf.keras)` আপনি কল করতে পারেন `share` আপনার মডেলটিকে টিএফ এনক্রিপ্ট(TF Encrypted) করা কেরাস মডেলে রূপান্তর করার পদ্ধতি।\n",
    "আপনি যদি উপরে সার্ভারগুলি ম্যানুয়ালি পরিচালনা করতে বলে থাকেন তবে সমস্ত পদক্ষেপ না নেওয়া পর্যন্ত এই পদক্ষেপটি সম্পূর্ণ হবে না। মনে রাখবেন যে আপনার ফায়ারওয়াল পাইথনকে(Python) গ্রহণ সংযোগ গ্রহণ করতে চাইতে পারে।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.share(cluster)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### মডেল পরিবেশন করুন (Serve model)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "নিখুঁত এখন ফোন করে calling `model.serve`আপনার মডেল কিছু ব্যক্তিগত ভবিষ্যদ্বাণী সরবরাহ করতে প্রস্তুত। আপনি সেট করতে পারেন `num_requests` মডেল দ্বারা পরিবেশন করা পূর্বাভাসের অনুরোধের সীমা নির্ধারণ করতে; যদি নির্দিষ্ট না করা হয় তবে মডেলটি বাধা দেওয়া পর্যন্ত পরিবেশন করা হবে।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.serve(num_requests=3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "আপনি এই অগ্রসর করতে প্রস্তুত **Part 13c** নোটবুক কিছু ব্যক্তিগত গণনা করতে।"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### পরিষ্করণ (Cleanup!)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "আপনার অনুরোধের উপরের সীমাটি উপরে উঠলে, মডেল আর সরবরাহের অনুরোধগুলির জন্য আর উপলভ্য হবে না, তবে এটি উপরের তিনটি কর্মীর মধ্যে এখনও গোপনীয়তার সাথে ভাগ করা আছে। আপনি নীচের সেলটি কার্যকর করে worker শেষ করতে পারেন।\n",
    "\n",
    "**অভিনন্দন** Part 13b সমাপ্তিতে সিফ্ট কেরাস(Syft Keras)এবং টিএফই(TFE) সহ নিরাপদ শ্রেণিবিন্যাস করার জন্য"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.stop()\n",
    "cluster.stop()\n",
    "\n",
    "if not AUTO:\n",
    "    process_ids = !ps aux | grep '[p]ython -m tf_encrypted.player --config' | awk '{print $2}'\n",
    "    for process_id in process_ids:\n",
    "        !kill {process_id}\n",
    "        print(\"Process ID {id} has been killed.\".format(id=process_id))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.17"
  },
  "nbTranslate": {
   "displayLangs": [
    "*"
   ],
   "hotkey": "alt-t",
   "langInMainMenu": true,
   "sourceLang": "en",
   "targetLang": "fr",
   "useGoogleTranslate": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
